package com.hzk.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzk.exception.GabalException;
import com.hzk.mapper.OrderMapper;
import com.hzk.pojo.*;
import com.hzk.service.*;
import com.hzk.utils.IdUtils;
import com.hzk.vo.CaseUser;
import com.hzk.vo.GoodsVo;
import com.hzk.vo.RespBeanEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jack
 * @since 2022-03-01
 */
@Transactional
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService, InitializingBean {

    @Autowired
    ISeckillGoodsService iSeckillGoodsService;
    @Autowired
    IUserBasicService iUserBasicService;
    @Autowired
    ISeckillOrderService iSeckillOrderService;
    @Autowired
    IGoodsService iGoodsService;
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ISanbankcService iSanbankcService;
    @Autowired
    RabbitTemplate rabbitTemplate;

    private String orderExchange="mayikt_order_exchange";//订单交换机


    private String orderRoutingKey="mayikt.order";//订单路由key

    private Long id;
    @Autowired
    private DefaultRedisScript<Long> script;
    private Map<Long, Boolean> EmptyStockMap = new HashMap<>();
    private Map<Long, Integer> CountStockMap = new HashMap<>();
    private int a;

    @Override
    public Order secKill(@CaseUser UserBasic userBasic, GoodsVo good,int money) {
        if (userBasic==null){
            return null;
        }
        UserBasic user = iUserBasicService.getById(userBasic.getId());
        ValueOperations valueOperations = redisTemplate.opsForValue();

        //拿到秒杀商品
        SeckillGoods goods = iSeckillGoodsService.getOne(new QueryWrapper<SeckillGoods>()
                .eq("goods_id", good.getId()));
        //做一个内存标记
        if (EmptyStockMap.get(good.getId())) {
            return null;
        }

        if (goods.getStockCount() < 1) {
            //判断是否还有库存
            valueOperations.set("isStockEmpty:" + goods.getGoodsId(), "0",15, TimeUnit.MINUTES);
            EmptyStockMap.put(good.getId(), true);
            return null;
        }

        //更新数据库之前先去判断一下数据库是不是为0
        boolean update = iSeckillGoodsService.update(new UpdateWrapper<SeckillGoods>()
                .setSql("stock_count=" + "stock_count-1")
                .eq("goods_id", good.getId()).gt("stock_count", 0));

        if (CountStockMap.get(good.getId()) == 0) {

            return null;
        }
        try {
            Order order = new Order();
            /*id=SnowFlake.getInstance().nextId();*/
            id = Long.parseLong(IdUtils.getPrimaryKey());
            order.setId(id);
            order.setUserId(user.getId());
            order.setGoodsId(good.getId());
            order.setDeliveryAddrId(0L);
            order.setGoodsName(good.getGoodsName());
            order.setGoodsCount(1);
            order.setGoodsPrice(goods.getSeckillPrice());
            order.setOrderChannel(1);
            order.setStatus("已支付");
            order.setCreateDate(new Date());
            orderMapper.inserts(order);
            /*iOrderService.save(order);*/


           /* //加入死信队列15分钟后检查
            rabbitTemplate.convertAndSend(orderExchange,orderRoutingKey,id,messagePostProcessor());*/


            //生成秒杀订单
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setOrderId(order.getId());
            seckillOrder.setGoodsId(good.getId());
            seckillOrder.setUserId(user.getId());
            iSeckillOrderService.save(seckillOrder);
            user.setCardMoney(user.getCardMoney()-money);
            iUserBasicService.updateById(user);
            redisTemplate.opsForValue().set("seckillorder:" + user.getId() + ":" + goods.getGoodsId(), seckillOrder);
            boolean id = iSanbankcService.update(new UpdateWrapper<Sanbankc>().eq("id", 1).setSql("account_money=" + "account_money+10000"));
            //redis减库存
            CountStockMap.put(good.getId(), CountStockMap.get(good.getId()) - 1);
            return order;
        } catch (Exception ex) {
            if (ex instanceof SQLIntegrityConstraintViolationException){
                SQLIntegrityConstraintViolationException e = (SQLIntegrityConstraintViolationException) ex;
                log.info(e.getMessage());
                return null;
            }
            log.info(ex.getMessage());
        }
        return null;
    }

    @Override
    public Order detail(UserBasic user, Long orderId) {
        if (user == null) {
            throw new GabalException(RespBeanEnum.NULL_USER_ERROR);
        }
        Order order = orderMapper.selectByIds(orderId);
        if (order == null) {
            throw new GabalException(RespBeanEnum.NULL_ORDER_ERROR);
        }
        return order;
    }

    @Override
    public Order getByIds(Long orderId) {
        Order order = orderMapper.selectByIds(orderId);
        return order;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> goodsVo = iGoodsService.findGoodsVo();

        if (CollectionUtils.isEmpty(goodsVo)) {
            return;
        }
        goodsVo.forEach(goodsVo1 -> {
            CountStockMap.put(goodsVo1.getId(), goodsVo1.getStockCount());
            EmptyStockMap.put(goodsVo1.getId(), false);
        });
    }
   /* //处理待发送消息（）
    private MessagePostProcessor messagePostProcessor(){
        return  new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置有效期30分钟
                //message.getMessageProperties().setExpiration("1800000");
                message.getMessageProperties().setExpiration("60000"); //15min后过期900000
                return message;
            }
        };
    }*/

}
